Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit e363738a9284a48fe4533cc68684dbe9db4803fe


Parents : bc796c6
Author : Ivan <ivan@quad4.io>
Signature : Signature validation error
Date : 2026-05-10T00:46:28-05:00

test(backend): fix failing tests for pytest compat, boolconfig mocks, and RNS get_instance

Changes
Diff

diff --git a/tests/backend/conftest.py b/tests/backend/conftest.py
index b2bbf70d..0da4d532 100644
--- a/tests/backend/conftest.py
+++ b/tests/backend/conftest.py
@@ -221,6 +221,7 @@ def mock_app(db, tmp_path, temp_db):
# a live provider for the same path as the db fixture.
app.database = Database(temp_db)
app.current_context.config = ConfigManager(app.database)
+ app.config = app.current_context.config
app.websocket_broadcast = MagicMock(side_effect=lambda data: None)
yield app

diff --git a/tests/backend/fixtures/http_api_routes.json b/tests/backend/fixtures/http_api_routes.json
index 9c938291..3c128772 100644
--- a/tests/backend/fixtures/http_api_routes.json
+++ b/tests/backend/fixtures/http_api_routes.json
@@ -248,6 +248,10 @@
"method": "POST",
"path": "/api/v1/favourites/add"
},
+ {
+ "method": "POST",
+ "path": "/api/v1/favourites/import"
+ },
{
"method": "DELETE",
"path": "/api/v1/favourites/{destination_hash}"

diff --git a/tests/backend/test_interface_discovery.py b/tests/backend/test_interface_discovery.py
index 2dd9ad6f..c29fff87 100644
--- a/tests/backend/test_interface_discovery.py
+++ b/tests/backend/test_interface_discovery.py
@@ -82,6 +82,7 @@ async def test_reticulum_discovery_get_and_patch(temp_dir):
storage_dir=temp_dir,
reticulum_config_dir=temp_dir,
)
+ app_instance.current_context.config.default_bootstrap_only.set(True)
get_handler = await find_route_handler(
app_instance,
@@ -145,7 +146,8 @@ async def test_reticulum_discovery_get_and_patch(temp_dir):
assert "interface_discovery_blacklist" not in config["reticulum"]
assert config["reticulum"]["required_discovery_value"] == 18
assert config["reticulum"]["autoconnect_discovered_interfaces"] == 5
- assert config["reticulum"]["default_bootstrap_only"] is False
+ assert "default_bootstrap_only" not in config["reticulum"]
+ assert app_instance.current_context.config.default_bootstrap_only.get() is False
assert config["reticulum"]["network_identity"] == "/tmp/other_id"
assert config.write_called

diff --git a/tests/backend/test_lxmf_propagation_sync_integration.py b/tests/backend/test_lxmf_propagation_sync_integration.py
index f702e4f9..c7af2e0d 100644
--- a/tests/backend/test_lxmf_propagation_sync_integration.py
+++ b/tests/backend/test_lxmf_propagation_sync_integration.py
@@ -61,6 +61,10 @@ class FakePropagationRouter:
self.propagation_transfer_state = self.PR_PATH_REQUESTED
self.propagation_transfer_progress = 0.0
+ def cancel_propagation_node_requests(self):
+ self.propagation_transfer_state = self.PR_IDLE
+ self.propagation_transfer_progress = 0.0
+
@pytest.fixture
def temp_dir():

diff --git a/tests/backend/test_security_fuzzing.py b/tests/backend/test_security_fuzzing.py
index ea1f406f..8a956b33 100644
--- a/tests/backend/test_security_fuzzing.py
+++ b/tests/backend/test_security_fuzzing.py
@@ -156,6 +156,23 @@ def mock_app():
app.config.auto_announce_enabled.get.return_value = False
app.config.voicemail_enabled.get.return_value = True
+ def _make_bool_mock(default=False):
+ mock = MagicMock()
+ mock.get.return_value = default
+
+ def _set(value):
+ mock.get.return_value = bool(value)
+
+ mock.set.side_effect = _set
+ return mock
+
+ app.config.block_all_from_strangers = _make_bool_mock(False)
+ app.config.block_attachments_from_strangers = _make_bool_mock(False)
+ app.config.lxmf_flood_protection_enabled.get.return_value = False
+ app.config.lxmf_flood_threshold_per_minute.get.return_value = 100
+ app.config.lxmf_flood_max_stamp_cost.get.return_value = 10
+ app.config.lxmf_inbound_stamp_cost.get.return_value = 2
+
# Surface mocks for tracking
app.is_destination_blocked = MagicMock(return_value=False)
app.check_spam_keywords = MagicMock(return_value=False)
@@ -2367,8 +2384,8 @@ class TestStrangerAttachmentBlocking:
source_hash = os.urandom(16)
mock_msg = self._make_mock_message(source_hash=source_hash)
- mock_app.config.block_attachments_from_strangers.get.return_value = True
- mock_app.config.block_all_from_strangers.get.return_value = False
+ mock_app.config.block_attachments_from_strangers.set(True)
+ mock_app.config.block_all_from_strangers.set(False)
mock_app._is_contact = MagicMock(return_value=False)
mock_app.is_destination_blocked = MagicMock(return_value=False)
mock_app.check_spam_keywords = MagicMock(return_value=False)
@@ -2386,8 +2403,8 @@ class TestStrangerAttachmentBlocking:
source_hash = os.urandom(16)
mock_msg = self._make_mock_message(source_hash=source_hash)
- mock_app.config.block_attachments_from_strangers.get.return_value = True
- mock_app.config.block_all_from_strangers.get.return_value = False
+ mock_app.config.block_attachments_from_strangers.set(True)
+ mock_app.config.block_all_from_strangers.set(False)
mock_app._is_contact = MagicMock(return_value=True)
mock_app.is_destination_blocked = MagicMock(return_value=False)
mock_app.check_spam_keywords = MagicMock(return_value=False)
@@ -2402,8 +2419,8 @@ class TestStrangerAttachmentBlocking:
source_hash = os.urandom(16)
mock_msg = self._make_mock_message(source_hash=source_hash)
- mock_app.config.block_attachments_from_strangers.get.return_value = False
- mock_app.config.block_all_from_strangers.get.return_value = False
+ mock_app.config.block_attachments_from_strangers.set(False)
+ mock_app.config.block_all_from_strangers.set(False)
mock_app._is_contact = MagicMock(return_value=False)
mock_app.is_destination_blocked = MagicMock(return_value=False)
mock_app.check_spam_keywords = MagicMock(return_value=False)
@@ -2421,8 +2438,8 @@ class TestStrangerAttachmentBlocking:
with_attachments=False,
)
- mock_app.config.block_attachments_from_strangers.get.return_value = True
- mock_app.config.block_all_from_strangers.get.return_value = False
+ mock_app.config.block_attachments_from_strangers.set(True)
+ mock_app.config.block_all_from_strangers.set(False)
mock_app._is_contact = MagicMock(return_value=False)
mock_app.is_destination_blocked = MagicMock(return_value=False)
mock_app.check_spam_keywords = MagicMock(return_value=False)
@@ -2456,8 +2473,8 @@ class TestStrangerAttachmentBlocking:
mock_msg.get_fields.return_value = fields
mock_msg.fields = fields
- mock_app.config.block_attachments_from_strangers.get.return_value = True
- mock_app.config.block_all_from_strangers.get.return_value = False
+ mock_app.config.block_attachments_from_strangers.set(True)
+ mock_app.config.block_all_from_strangers.set(False)
mock_app._is_contact = MagicMock(return_value=False)
mock_app.is_destination_blocked = MagicMock(return_value=False)
mock_app.check_spam_keywords = MagicMock(return_value=False)
@@ -2494,8 +2511,8 @@ class TestStrangerAttachmentBlocking:
mock_msg.get_fields.return_value = fields
mock_msg.fields = fields
- mock_app.config.block_attachments_from_strangers.get.return_value = True
- mock_app.config.block_all_from_strangers.get.return_value = False
+ mock_app.config.block_attachments_from_strangers.set(True)
+ mock_app.config.block_all_from_strangers.set(False)
mock_app._is_contact = MagicMock(return_value=True)
mock_app.is_destination_blocked = MagicMock(return_value=False)
mock_app.check_spam_keywords = MagicMock(return_value=False)
@@ -2535,8 +2552,8 @@ class TestBlockAllFromStrangers:
def test_stranger_message_dropped_when_enabled(self, mock_app):
"""Text message from a stranger is silently dropped when block_all is on."""
mock_msg = self._make_mock_message()
- mock_app.config.block_all_from_strangers.get.return_value = True
- mock_app.config.block_attachments_from_strangers.get.return_value = False
+ mock_app.config.block_all_from_strangers.set(True)
+ mock_app.config.block_attachments_from_strangers.set(False)
mock_app._is_contact = MagicMock(return_value=False)
mock_app.is_destination_blocked = MagicMock(return_value=False)
mock_app.check_spam_keywords = MagicMock(return_value=False)
@@ -2547,8 +2564,8 @@ class TestBlockAllFromStrangers:
def test_contact_message_delivered_when_block_all_enabled(self, mock_app):
"""Messages from contacts pass through even when block_all is on."""
mock_msg = self._make_mock_message()
- mock_app.config.block_all_from_strangers.get.return_value = True
- mock_app.config.block_attachments_from_strangers.get.return_value = False
+ mock_app.config.block_all_from_strangers.set(True)
+ mock_app.config.block_attachments_from_strangers.set(False)
mock_app._is_contact = MagicMock(return_value=True)
mock_app.is_destination_blocked = MagicMock(return_value=False)
mock_app.check_spam_keywords = MagicMock(return_value=False)
@@ -2559,8 +2576,8 @@ class TestBlockAllFromStrangers:
def test_stranger_with_attachments_dropped(self, mock_app):
"""Message with attachments from stranger is dropped entirely, not just stripped."""
mock_msg = self._make_mock_message(with_attachments=True)
- mock_app.config.block_all_from_strangers.get.return_value = True
- mock_app.config.block_attachments_from_strangers.get.return_value = True
+ mock_app.config.block_all_from_strangers.set(True)
+ mock_app.config.block_attachments_from_strangers.set(True)
mock_app._is_contact = MagicMock(return_value=False)
mock_app.is_destination_blocked = MagicMock(return_value=False)
mock_app.check_spam_keywords = MagicMock(return_value=False)
@@ -2571,8 +2588,8 @@ class TestBlockAllFromStrangers:
def test_disabled_allows_stranger_messages(self, mock_app):
"""When block_all is off, stranger messages are delivered."""
mock_msg = self._make_mock_message()
- mock_app.config.block_all_from_strangers.get.return_value = False
- mock_app.config.block_attachments_from_strangers.get.return_value = False
+ mock_app.config.block_all_from_strangers.set(False)
+ mock_app.config.block_attachments_from_strangers.set(False)
mock_app._is_contact = MagicMock(return_value=False)
mock_app.is_destination_blocked = MagicMock(return_value=False)
mock_app.check_spam_keywords = MagicMock(return_value=False)

diff --git a/tests/backend/test_telemetry_integration.py b/tests/backend/test_telemetry_integration.py
index 85ea40ec..5e5a2990 100644
--- a/tests/backend/test_telemetry_integration.py
+++ b/tests/backend/test_telemetry_integration.py
@@ -34,6 +34,9 @@ def mock_app():
# Mock websocket_broadcast
app.websocket_broadcast = MagicMock()
+ # Required attribute for on_lxmf_delivery flood protection
+ app._lxmf_incoming_timestamps = []
+
# Attach the actual method we want to test if possible,
# but since it's an instance method, we might need to bind it.
app.process_incoming_telemetry = (
@@ -112,12 +115,13 @@ async def test_telemetry_request_parsing(mock_app):
)
mock_app.is_destination_blocked.return_value = False
- mock_app.current_context.config.telemetry_enabled.get.return_value = True
+ mock_app.current_context.config.telemetry_enabled.set(True)
mock_app.database.contacts.get_contact_by_identity_hash.return_value = {
"is_telemetry_trusted": True,
}
mock_app.database.messages.get_lxmf_message_by_hash.return_value = {}
- mock_app.database.config.get.side_effect = lambda k: 50.0 if "lat" in k else 10.0
+ mock_app.database.config.set("map_default_lat", 50.0)
+ mock_app.database.config.set("map_default_lon", 10.0)
mock_app.on_lxmf_delivery(mock_lxmf_message)
@@ -142,12 +146,13 @@ async def test_telemetry_request_no_location_does_not_call_handler(mock_app):
)
mock_app.is_destination_blocked.return_value = False
- mock_app.current_context.config.telemetry_enabled.get.return_value = True
+ mock_app.current_context.config.telemetry_enabled.set(True)
mock_app.database.contacts.get_contact_by_identity_hash.return_value = {
"is_telemetry_trusted": True,
}
mock_app.database.messages.get_lxmf_message_by_hash.return_value = {}
- mock_app.database.config.get.return_value = None
+ mock_app.database.config.set("map_default_lat", None)
+ mock_app.database.config.set("map_default_lon", None)
mock_app.on_lxmf_delivery(mock_lxmf_message)

diff --git a/tests/backend/test_websocket_interfaces.py b/tests/backend/test_websocket_interfaces.py
index 3888a889..fa2fe8b2 100644
--- a/tests/backend/test_websocket_interfaces.py
+++ b/tests/backend/test_websocket_interfaces.py
@@ -21,8 +21,12 @@ class TestWebsocketInterfaces(unittest.TestCase):
self.port = s.getsockname()[1]
s.close()
+ @patch("RNS.Reticulum")
@patch("RNS.Interfaces.Interface.Interface.get_config_obj")
- def test_server_initialization(self, mock_get_config):
+ def test_server_initialization(self, mock_get_config, mock_rns):
+ mock_rns.get_instance.return_value = MagicMock(
+ _default_ic_max_held_announces=MagicMock(return_value=256),
+ )
config = {
"name": "test_ws_server",
"listen_ip": "127.0.0.1",
@@ -39,8 +43,12 @@ class TestWebsocketInterfaces(unittest.TestCase):
if server.server:
server.server.shutdown()
+ @patch("RNS.Reticulum")
@patch("RNS.Interfaces.Interface.Interface.get_config_obj")
- def test_client_initialization(self, mock_get_config):
+ def test_client_initialization(self, mock_get_config, mock_rns):
+ mock_rns.get_instance.return_value = MagicMock(
+ _default_ic_max_held_announces=MagicMock(return_value=256),
+ )
config = {"name": "test_ws_client", "target_url": f"ws://127.0.0.1:{self.port}"}
mock_get_config.return_value = config


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────